﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using AzukiMap.MapSource;
using AzukiMap.Renderer;
using GeoAPI.Geometries;
using GisSharpBlog.NetTopologySuite.Geometries;

namespace AzukiMap.Layer
{
    public delegate int LocalVectorGetThemeIdHandler(object sender, LocalVectorData item);
    public delegate IVectorStyle LocalVectorGetStyleHandler(object sender, LocalVectorData item);

    public class LocalVectorLayer : VectorLayer
    {
        public event LocalVectorGetThemeIdHandler GetThemeId;
        protected virtual int OnGetThemeId(object sender, LocalVectorData item)
        {
            if (GetThemeId != null)
            {
                return GetThemeId(this, item);
            }
            return item.ExpressionId;
        }

        public event LocalVectorGetStyleHandler GetStyleEvent;
        protected virtual IVectorStyle OnGetStyle(object sender, LocalVectorData item)
        {
            if (GetStyleEvent != null)
            {
                return GetStyleEvent(this, item);
            }
            return DefaultStyle;
        }

        public IList<LocalVectorData> GetSelectedSources()
        {
            var sources = SelectedElementIds.Select(id => LocalVectorSource.GetSourceById(id)).ToList();
            return sources;
        }

        protected virtual IVectorStyle GetStyle(LocalVectorData item)
        {
            if (GetStyleEvent != null)
            {
                return OnGetStyle(this, item);
            }
            else
            {
                int themeId = item.ExpressionId;

                if (GetThemeId != null)
                {
                    themeId = OnGetThemeId(this, item);
                }

                if (themeId == -1)
                {
                    return DefaultStyle;
                }
                else
                {
                    if (LayerThemes.Count > themeId)
                    {
                        return LayerThemes[themeId].Style;
                    }
                    else
                    {
                        return DefaultStyle;
                    }
                }
            }
        }

        public LocalVectorLayer()
        {
        }

        public LocalVectorLayer(LocalVectorSource vectorSource, string name )
        {
            LocalVectorSource = vectorSource;
            Name = name;
        }

        public LocalVectorLayer(LocalVectorSource vectorSource, string name, IPolygon maxExtent)
        {
            LocalVectorSource = vectorSource;
            Name = name;
            MaxExtent = maxExtent;
        }


        public LocalVectorSource LocalVectorSource
        {
            get { return (LocalVectorSource) VectorSource; }
            set
            {
                if (value == null)
                    throw new ArgumentNullException();

                base.VectorSource = value;
            }
        }

        public override void Draw()
        {
            base.Draw();
            if (IsRendering)
            {
                return;
            }
            if (!IsVisible)
            {
                return;
            }
            if (!CheckScale())
            {
                return;
            }
            // return when not drawable
            if (!IsDrawable)
            {
                return;
            } 
            IsRendering = true;

            // TODO: 
            Clear();

            IVectorStyle vStyle;

            _renderer.StartRendering();
            foreach (LocalVectorData item in LocalVectorSource.GetItemsInExtent(CurrentExtent))
            {
                if (_rendered.ContainsKey(item.Id))
                {
                    continue;
                }

                vStyle = GetStyle(item);

                List<FrameworkElement> elems = _renderer.DrawGeometry(item.Id, item.Geometry, vStyle);

                if ( SelectedElementIds.Contains(item.Id))
                {
                    foreach( var element in elems )
                    {
                        SetAsSelected(item.Id, element);
                    }
                }

                _rendered.Add(item.Id, true);

                RenderedElements[item.Id] = elems;

                SetElementAttr(item, elems);
            }
            _renderer.FinishRendering();
         
            IsRendering = false;
        }

        virtual protected void SetElementAttr(LocalVectorData item, List<FrameworkElement> elems) {
            SetEventsOnElement(elems);
        }

        protected override void TransformLocalItems(int targetSrid)
        {
            base.TransformLocalItems(targetSrid);
            LocalVectorSource.TransformItems(targetSrid);
        }
    }
}